package com.cloud.user_info.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.annex.AnnexUrlService;
import com.cloud.common.domain.Result;
import com.cloud.entity.SysApply;
import com.cloud.entity.SysRole;
import com.cloud.common.enums.MenuType;
import com.cloud.exception.CustomException;
import com.cloud.user_info.mapper.SysApplyMapper;
import com.cloud.user_info.service.ISysApplyService;
import com.cloud.user_info.service.ISysRoleService;
import com.cloud.utils.StringUtils;
import com.cloud.utils.SystemUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 应用管理
 *
 * @author yzj
 * @since 2022-08-11
 */
@Service
public class SysApplyServiceImpl extends ServiceImpl<SysApplyMapper, SysApply> implements ISysApplyService {

    @Resource
    private SysApplyMapper sysApplyMapper;

    @Resource
    private AnnexUrlService annexUrlService;

    @Autowired
    private ISysRoleService roleService;

    /**
     * 根据角色ID查询应用列表
     *
     * @author yzj
     */
    @Override
    public List<SysApply> selectSysApplyList(SysApply sysApply) {
        List<SysApply> applyList = null;
        if (SystemUtils.isAdmin(sysApply.getUserId())) {
            applyList = sysApplyMapper.selectApplyUserById(sysApply, null);
        } else {
            // 根据用户ID查询项目角色ID数组
            String roleIds = roleService.selectProjectRoleIds(sysApply.getSysCode(), sysApply.getUserId());
            applyList = sysApplyMapper.selectApplyUserById(sysApply, roleIds);
        }
        if (applyList.size() > 0) {
            for (SysApply apply : applyList) {
                apply.setAppImage(annexUrlService.getImageTurnPath(apply.getAppImage()));
            }
        }
        return applyList;
    }

    /**
     * 应用管理新增
     *
     * @author yzj
     */
    @Override
    public int insertObject(SysApply sysApply) {
        SysApply applyInfo = sysApplyMapper.selectAppInfoByName(sysApply.getAppName());
        if (StringUtils.isNotNull(applyInfo)) {
            throw new CustomException("操作失败:应用名称已存在");
        }
        return sysApplyMapper.insert(sysApply);
    }

    /**
     * 应用管理修改
     *
     * @author yzj
     */
    @Override
    public int updateObject(SysApply sysApply) {
        SysApply applyInfo = sysApplyMapper.selectAppInfoByName(sysApply.getAppName());
        if (StringUtils.isNotNull(applyInfo)) {
            if (sysApply.getId() != applyInfo.getId()) {
                throw new CustomException("操作失败:应用名称已存在");
            }
        }
        return sysApplyMapper.updateById(sysApply);
    }

    /**
     * 根据角色ID查询应用树信息
     *
     * @param roleId
     * @return
     */
    @Override
    public List<Integer> selectApplyListById(Long roleId) {
        SysRole roleInfo = roleService.selectRoleById(roleId);
        if (StringUtils.isNull(roleInfo)) {
            throw new CustomException("查询角色信息不存在");
        }
        return sysApplyMapper.selectApplyListById(roleId, roleInfo.isApplyCheckStrictly());
    }


    /**
     * 构建前端所需要树结构
     *
     * @param sysApply
     * @return 树结构列表
     */
    @Override
    public List<SysApply> buildApplyTree(SysApply sysApply) {
        List<SysApply> returnList = new ArrayList<>();
        List<SysApply> applyList = selectSysApplyList(sysApply);
        if (applyList.size() <= 0) {
            return returnList;
        }
        List<Long> tempList = new ArrayList<>();
        for (SysApply apply : applyList) {
            tempList.add(apply.getId());
            // 如果是顶级节点,遍历该父节点的所有子节点
            if (!tempList.contains(apply.getParentId())) {
                recursionFn(applyList, apply);
                returnList.add(apply);
            }
        }
        if (returnList.isEmpty()) {
            returnList = applyList;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list 集合
     * @param t    menu对象
     */
    private void recursionFn(List<SysApply> list, SysApply t) {
        // 得到子节点列表
        List<SysApply> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysApply tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysApply> getChildList(List<SysApply> list, SysApply t) {
        List<SysApply> tlist = new ArrayList<>();
        for (SysApply n : list) {
            if (n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysApply> list, SysApply t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * 移动端查询应用列表树
     */
    @Override
    public Result getUserApplyList(SysApply sysApply) {
        List<Tree<Long>> buildList = new ArrayList<>();
        List<SysApply> applyList = selectSysApplyList(sysApply);
        if (StringUtils.isNull(applyList)) {
            return Result.success("查询成功", buildList);
        }
        sysApply.setStatus(MenuType.APPLY_SHOW.getCode());
        TreeNodeConfig config = new TreeNodeConfig();
        config.setIdKey("id");
        // 父节点字段名称
        config.setParentIdKey("parentId");
        config.setWeightKey("orderNum");
        // 转树,Tree<>里面泛型为Long 的类型
        buildList = TreeUtil.build(applyList, 0L, config, (object, tree) -> {
            Field[] fields = ReflectUtil.getFieldsDirectly(object.getClass(), true);
            for (Field field : fields) {
                String fieldName = field.getName();
                Object fieldValue = ReflectUtil.getFieldValue(object, field);
                tree.putExtra(fieldName, fieldValue);
            }
        });
        return Result.success("查询成功", buildList);
    }

    /**
     * 根据应用id查询详情
     *
     * @param applyId
     * @return
     */
    @Override
    public SysApply getObjectInfo(Long applyId) {
        SysApply sysApply = sysApplyMapper.selectById(applyId);
        if (StringUtils.isNotNull(sysApply)) {
            sysApply.setAppImage(annexUrlService.getImageTurnPath(sysApply.getAppImage()));
        }
        return sysApply;
    }

}
